package Skill

import (
	codecs "sanguo/codec/cs"
	com_attr "sanguo/node/common/attr"
	"sanguo/node/common/transaction"
	"sanguo/node/node_game"
	"sanguo/node/node_game/module/role"
	"sanguo/node/node_game/user"
	table_SkillLevel "sanguo/node/table/excel/table/SkillLevel"
	cs_message "sanguo/protocol/cs/message"
	"time"

	"github.com/golang/protobuf/proto"
)

type transactionSkillLevelUp struct {
	transaction.TransactionBase
	user    *user.User
	req     *codecs.Message
	resp    *cs_message.SkillLevelupToC
	errcode cs_message.EnumType
}

func (this *transactionSkillLevelUp) GetModuleName() string {
	return "Skill"
}

func (this *transactionSkillLevelUp) GetReplyMsg() proto.Message {
	return &cs_message.SkillLevelupToC{}
}

func (this *transactionSkillLevelUp) SetExpiredTime(expired time.Time) {
	this.Expired = expired
}

func (this *transactionSkillLevelUp) GetExpiredTime() time.Time {
	return this.Expired
}

func (this *transactionSkillLevelUp) Begin() {

	this.resp = &cs_message.SkillLevelupToC{}
	msg := this.req.GetData().(*cs_message.SkillLevelupToS)
	roleModule := this.user.GetModuleByName("role").(*role.RoleModule)
	role := roleModule.CurrentRole()

	if nil == role || !role.IsRoleModleData() {
		node_game.Infoln(this.user.GetUserID(), "skill_levelup fail:no select role")
		this.errcode = cs_message.EnumType_ERROR
		this.user.EndTrans(this)
		return
	}
	node_game.Infof("%s %d Call SkillLevelUp type:%d id:%d", role.GetUserID(), role.GetID(), msg.GetSkillType(), msg.GetSkillID())

	roleSkill := role.GetRoleSkill()
	if !roleSkill.CheckSkill(msg.GetSkillType(), msg.GetSkillID()) {
		node_game.Infoln(role.GetUserID(), role.GetID(), "skill_levelup fail:checkskill fail")
		this.errcode = cs_message.EnumType_ERROR
		this.user.EndTrans(this)
		return
	}

	skill := roleSkill.GetSkill(msg.GetSkillType(), msg.GetSkillID())

	//技能点判断
	SlDef := table_SkillLevel.Table_.IDMap[skill.Level]
	NextSlDef := table_SkillLevel.Table_.IDMap[skill.Level+1]
	if SlDef == nil || NextSlDef == nil {
		node_game.Infoln(role.GetUserID(), role.GetID(), "skill_levelup fail:SlDef is nil")
		this.errcode = cs_message.EnumType_ERROR
		this.user.EndTrans(this)
		return
	}

	gold, _ := role.GetRoleAttr().GetAttr(com_attr.Gold)
	gold -= int64(SlDef.CostGold)
	if gold < 0 {
		node_game.Infoln(role.GetUserID(), role.GetID(), "skill_levelup fail:gold not enough")
		this.errcode = cs_message.EnumType_ERROR
		this.user.EndTrans(this)
		return
	}

	if !roleSkill.LevelUp(msg.GetSkillType(), msg.GetSkillID()) {
		node_game.Infoln(role.GetUserID(), role.GetID(), "skill_levelup fail: LevelUp fail")
		this.errcode = cs_message.EnumType_ERROR
		this.user.EndTrans(this)
		return
	}

	role.GetRoleAttr().SetAttr(com_attr.Gold, gold)
	role.OnSkillDirty()

	node_game.Infoln(role.GetUserID(), role.GetID(), "skill_levelup OK")
	this.errcode = cs_message.EnumType_OK
	this.user.EndTrans(this)

}

func (this *transactionSkillLevelUp) End() {
	this.resp.Errcode = cs_message.EnumType(this.errcode).Enum()
	this.user.Reply(this.req.GetSeriNo(), this.resp)
}

func (this *transactionSkillLevelUp) Timeout() {
	this.resp.Errcode = cs_message.EnumType(cs_message.EnumType_RETRY).Enum()
	this.user.EndTrans(this)
}

func init() {
	user.RegisterTransFunc(&cs_message.SkillLevelupToS{}, func(user *user.User, msg *codecs.Message) transaction.Transaction {
		return &transactionSkillLevelUp{
			user: user,
			req:  msg,
		}
	})
}
